ConcurrentHashMap 和 Hashtable 的区别

底层数据结构

ConcurrentHashMap

[JDK1.7]
ConcurrentHashMap 底层采用 分段的数组+链表 实现,
[JDK1.8]
ConcurrentHashMap 采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。

Hashtable

Hashtable 和 JDK1.8 之前的 HashMap 的底层数据结构类似都是采用 数组+链表 的形式,
数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的;

实现线程安全的方式(重要)

ConcurrentHashMap

[JDK1.7]
ConcurrentHashMap(分段锁) 对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,
就不会存在锁竞争,提高并发访问率。
[JDK1.8]
摒弃了Segment的概念,而是直接用 Node 数组 + 链表 + 红黑树 的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作。
(JDK1.6以后 对 synchronized锁做了很多优化) 整个看起来就像是优化过且线程安全的 HashMap,
虽然在JDK1.8中还能看到 Segment 的数据结构,但是已经简化了属性,只是为了兼容旧版本;

Hashtable(同一把锁)

使用 synchronized 来保证线程安全,效率非常低下。当一个线程访问同步方法时,其他线程也访问同步方法,
可能会进入阻塞或轮询状态,如使用 put 添加元素,另一个线程不能使用 put 添加元素,也不能使用 get,
竞争会越来越激烈效率越低。HashTable性能差主要是由于所有操作需要竞争同一把锁,而如果容器中有多把锁,
每一把锁锁一段数据,这样在多线程访问时不同段的数据时,就不会存在锁竞争了,这样便可以有效地提高并发效率。
这就是ConcurrentHashMap所采用的”分段锁”思想。

HashTable:

HashTable全表锁

JDK1.7的ConcurrentHashMap:

JDK1.7的ConcurrentHashMap

JDK1.8的ConcurrentHashMap(TreeBin: 红黑二叉树节点 Node: 链表节点):

JDK1.8的ConcurrentHashMap